package compilarclassejava;

import java.lang.reflect.Method;
import java.util.LinkedList;

import entidadesparaguardardadosteste.CasoDeTeste;
import gui.AssociaClassesEMetodosANomes;
import gui.DeclaracaoDeMetodo;
import gui.FachadaManipulacaoClassesDeUmProjeto;

/*essa classe irah criar varios casos de teste soh para pegar valores para cada uma das
 *variaveis que substituem os system.out da classe .java a ser testada.
 *Para isso, ela precisa dos valores que o usuario forneceu para cada uma dessas variaveis*/
public class PreparaCasosDeTesteGetVariaveisSaida 
{
	private LinkedList<String> valoresFornecidosPeloUsuarioParaVariaveisSystemOut;
	
	private LinkedList<DeclaracaoDeMetodo> metodosComSetsParaVariaveisSystemOut;
	private int quantasVariaveisForamCriadasParaSystemOut;
	
	public PreparaCasosDeTesteGetVariaveisSaida
				(LinkedList<String> valoresFornecidosPeloUsuarioParaVariaveisSystemOut)
	{
		this.valoresFornecidosPeloUsuarioParaVariaveisSystemOut =
							valoresFornecidosPeloUsuarioParaVariaveisSystemOut;
		this.quantasVariaveisForamCriadasParaSystemOut = 0;
	}
	
	public LinkedList<CasoDeTeste> criarCasosDeTesteGetVariaveisEntradaSaida(String enderecoParaArquivoJavaQueCriamos)
	{
		String caminhoAteNovaPastaComJavaEClassQueCriamos = "backupsTestable";
		
		String nomeClasseAssociadaAoCasoDeTeste =
				obterNomeDaClasseASerTestada(enderecoParaArquivoJavaQueCriamos);
		
		FachadaManipulacaoClassesDeUmProjeto fachadaClassesDeUmProjeto =
									FachadaManipulacaoClassesDeUmProjeto.getInstance();
		AssociaClassesEMetodosANomes conhecedorDasClassesDoProjetoESeusNomes =
									fachadaClassesDeUmProjeto.getAssociaClassesEMetodosANomes();
		@SuppressWarnings("rawtypes")
		Class classeQueVamosTestar = conhecedorDasClassesDoProjetoESeusNomes.pegarClasseDeNome(nomeClasseAssociadaAoCasoDeTeste);
		
		this.pegarTodasAsDeclaracoesDeMetodosGetParaSaidas
							(classeQueVamosTestar, enderecoParaArquivoJavaQueCriamos);
		
		
		LinkedList<CasoDeTeste> casosDeTesteSetVariaveisEntradaSaida =
				this.criarCasosDeTesteComBaseEmInformacoesRecolhidas
					(caminhoAteNovaPastaComJavaEClassQueCriamos, nomeClasseAssociadaAoCasoDeTeste);
		
		return casosDeTesteSetVariaveisEntradaSaida;
		
	}
	
	private void pegarTodasAsDeclaracoesDeMetodosGetParaSaidas
							(@SuppressWarnings("rawtypes") Class classeQueVamosTestar, String enderecoParaArquivoJavaQueCriamos)
	{
		metodosComSetsParaVariaveisSystemOut = new LinkedList<DeclaracaoDeMetodo>();
		Method[] metodosDaClasse = classeQueVamosTestar.getMethods();
		
		int percorredorMetodosDaClasse = 0;
		while(percorredorMetodosDaClasse < metodosDaClasse.length)
		{
			Method umMetodo = metodosDaClasse[percorredorMetodosDaClasse];
			if(umMetodo.getName().contains("getVariavelTestTableSaida" + quantasVariaveisForamCriadasParaSystemOut) == true)
			{
				DeclaracaoDeMetodo declaracaoUmMetodo =
						new DeclaracaoDeMetodo(umMetodo, enderecoParaArquivoJavaQueCriamos);
				declaracaoUmMetodo.setCabecalhoDoMetodo("String getVariavelTestTableSaida" + this.quantasVariaveisForamCriadasParaSystemOut);
				this.quantasVariaveisForamCriadasParaSystemOut =
						quantasVariaveisForamCriadasParaSystemOut + 1;
				this.metodosComSetsParaVariaveisSystemOut.add(declaracaoUmMetodo);
				
				percorredorMetodosDaClasse = 0;
			}
			else
			{
				percorredorMetodosDaClasse = percorredorMetodosDaClasse + 1;
			}
		}
	}
	
	private String obterNomeDaClasseASerTestada(String enderecoParaArquivoJavaModificado)
	{
		String[] stringSplitadaPorBarras = enderecoParaArquivoJavaModificado.split("/");
		String parteDoEnderecoComNomeDaClasseEExtensaoJava =
				stringSplitadaPorBarras[stringSplitadaPorBarras.length - 1];
		String nomeClasseJavaSemExtensao =
				parteDoEnderecoComNomeDaClasseEExtensaoJava.replaceAll(".java", "");
		nomeClasseJavaSemExtensao = nomeClasseJavaSemExtensao.replace(".c", "");
		String nomeClasseASerTestada = nomeClasseJavaSemExtensao.replace(" ", "");
		
		return nomeClasseASerTestada;
	}
	
	
	private LinkedList<CasoDeTeste> criarCasosDeTesteComBaseEmInformacoesRecolhidas
					(String enderecoDoProjetoDaClasseATestar, String nomeClasseAssociadaAoCasoDeTeste)
	{
		LinkedList<CasoDeTeste> casosDeTesteCriados = new LinkedList<CasoDeTeste>();
		
		/*definir casos de uso com gets para variaveis que substituem system.outs*/
		int quantasVariaveisSystemOutForamCriadas =
				valoresFornecidosPeloUsuarioParaVariaveisSystemOut.size();
		for(int j = 0; j < quantasVariaveisSystemOutForamCriadas; j++)
		{
			CasoDeTeste casoDeTeste = new CasoDeTeste();
			casoDeTeste.setIdCasoDeTeste(9999 + j);
			casoDeTeste.setEnderecoDoProjetoDaClasseATestar(enderecoDoProjetoDaClasseATestar);
			casoDeTeste.setNomeClasseAssociadaAoCasoDeTeste(nomeClasseAssociadaAoCasoDeTeste);
			casoDeTeste.setMetodo(this.metodosComSetsParaVariaveisSystemOut.get(j));
			
			
			String valorParaGetDeUmaVariavelSystemOut =
					this.valoresFornecidosPeloUsuarioParaVariaveisSystemOut.get(j);
			LinkedList<Object> entradasDoMetodo = new LinkedList<Object>();
			
			casoDeTeste.setValoresDosParametrosDoMetodo(entradasDoMetodo); //metodos get() nao tem entrada
			casoDeTeste.setValorEsperadoDaSaida(valorParaGetDeUmaVariavelSystemOut); 
			casoDeTeste.setCasoDeTesteEstahCompleto(true);
			
			casosDeTesteCriados.add(casoDeTeste);
		}
		
		return casosDeTesteCriados;
	}
}
